package mpbft

import (
	"blockchain/public/function"
	"bytes"
	"encoding/json"
)

type prepare2Message struct{
	tradeHash [32]byte
	prepareSet1 [N/3+1]prepare1Message
	sign string
	priSeq int
}

func prepare2(priSeq int){
	var prepare2 prepare2Message
	data:= make([][]byte,2)
	prepare2.prepareSet1,prepare2.tradeHash=priGetMessagemm(priSeq)
	//fmt.Println(prepare2.prepareSet1[0])
	data[0],_=json.Marshal(prepare2.prepareSet1)
	data[1],_=json.Marshal(prepare2.tradeHash)
	data1:=bytes.Join(data,[]byte(""))
	prepare2.sign=function.Sign(data1,priSeq)
	prepare2.priSeq=priSeq
	var flagPrepared2 =make(chan bool)
	go sendPrepare0ToNode(priSeq,flagPrepared2,&prepare2)
	<-flagPrepared2
}

func sendPrepare0ToNode(priSeq int,flagPrepared2 chan bool,prepare2 *prepare2Message){
	for i:=0;i<N;i++{
		select {
		case chanNodeRecPrepare2[i]<-*prepare2:
			FlagPrepared2[priSeq][i]<-true
			close(FlagPrepared2[priSeq][i])
		default:
			FlagPrepared2[priSeq][i]<-false
			close(FlagPrepared2[priSeq][i])
		}
	}
	flagPrepared2<-true
	close(flagPrepared2)
}


func priGetMessagemm(priSeq int)([N/3+1] prepare1Message,[32]byte){//获取一致的交易信息
	var prepareSet1 [2*N/3+1]prepare1Message
	var prepareSet1Veried [2*N/3+1] prepare1Message
	var prepare1Same [2*N/3+1] int
	var counter [2*N/3+1] int
	var mesSet[N/3+1] prepare1Message
	var tradehashm [32]byte

	var state[2*N/3+1] int

	for i:=0;i<2*N/3+1;i++{
		prepare1Same[i]=N
		state[i]=0
	}

	count:=0
	for data:=range chanPriRecPrepare1[priSeq]{//取出prepare1消息
		prepareSet1[count]=data
		count++
	}
	count=0
	for i:=0;i<(N/3+1);i++{
				counter[i]=0
				for j:=i;j<(2*N/3+1);j++{
					if state[j]==0{
						//data:=prepareSet1[j].tradeHash
						res:=function.VerifySignHash(prepareSet1[j].tradeHash,prepareSet1[j].sign,prepareSet1[j].nodeSeq)
						if res{
							state[j]=1
							prepareSet1Veried[count]=prepareSet1[j]
							count++
						}else {
							state[j]=2
							//fmt.Printf("%d是拜占庭\n",prepareSet1[j].nodeSeq)
						}
					}
					if state[j]==1{
						if prepareSet1[j].tradeHash==prepareSet1[i].tradeHash{
							counter[i]++
							prepare1Same[j]=i
						}
					}
					if counter[i]>N/3{
						break;
					}
				}
				if counter[i]>N/3{
					break;
				}
	}
	count=0
	for i:=0;i<2*N/3+1;i++{
		if counter[i]>N/3{
			tradehashm=prepareSet1Veried[i].tradeHash
			mesSet[count]=prepareSet1Veried[i]
			count=1
			for j:=i+1;j<2*N/3+1;j++{
				if prepare1Same[j]==i{
					//println(count)
					mesSet[count]=prepareSet1Veried[j]
					//fmt.Println(prepareSet1Veried[j])
					count++
					if count==N/3+1{
						break
					}
				}
			}
			//println(countSame[i])
		}
	}
	return mesSet,tradehashm
}


func priGetMessage(priSeq int)([N/3+1] prepare1Message,[32]byte){//获取一致的交易信息
	var prepareSet1 [2*N/3+1]prepare1Message
	var prepareSet1Veried [2*N/3+1] prepare1Message
	var prepare1Same [2*N/3+1] int
	var counter [2*N/3+1] int
	var mesSet[N/3+1] prepare1Message
	var tradehash [32]byte

	for i:=0;i<2*N/3+1;i++{
		prepare1Same[i]=N
	}

	count:=0
	for data:=range chanPriRecPrepare1[priSeq]{//取出prepare1消息
		prepareSet1[count]=data
		count++
	}
	count=0
	for i:=0;i<2*N/3+1;i++{//获取消息与签名一致的prepare1
		data:=prepareSet1[i].tradeHash
		res:=function.VerifySignHash(data,prepareSet1[i].sign,prepareSet1[i].nodeSeq)
		if !res{
			//fmt.Printf("节点%d消息签名不一致",prepareSet1[i].nodeSeq)
		}else {
			prepareSet1Veried[count]=prepareSet1[i]
			count++
		}
	}

	for i:=0;i<2*N/3+1;i++{
		if prepareSet1Veried[i].sign!=""{
			if prepare1Same[i]==N{
				counter[i]=1
				prepare1Same[i]=i
				for j:=i+1;j<2*N/3;j++{
					if prepareSet1Veried[j].tradeHash==prepareSet1Veried[i].tradeHash{
						counter[i]++
						prepare1Same[j]=i

					}
				}
			}
		}
	}
	count=0
	for i:=0;i<2*N/3+1;i++{
		if counter[i]>N/3{
			tradehash=prepareSet1Veried[i].tradeHash
			mesSet[count]=prepareSet1Veried[i]
			count=1
			for j:=i+1;j<2*N/3+1;j++{
				if count==N/3+1{
					break;
				}
				if prepare1Same[j]==i{
					mesSet[count]=prepareSet1Veried[j]
					count++
				}
			}
			//println(countSame[i])
		}
	}
	return mesSet,tradehash
}
